﻿using LightCAD.Core.Element3d;
using LightCAD.Runtime.Interface;

namespace LightCAD.Model
{

    public class Cylinder3dAction : Solid3dAction
    {
        private LcCylinder cylinder = null;

        public Cylinder3dAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令：Cylinder");
        }
        public async void ExecCreate(string[] args = null)
        {
            StartAction();
            Vector3 startP = null;
            Vector3 endP = null;
            PointInputer3d pointer = new PointInputer3d(docEditor);
            FaceInputerResult pr = null;
            PlanarSurface3d plane = null;
            LcSolid3d solidEle = null;
            bool startPush = false;
            this.model3dRuntime.EnableCameraControl(false);
            this.snap3dRuntime.AddSnapPlanes(new ListEx<Plane>
            {
                new Plane().SetFromNormalAndCoplanarPoint(new Vector3(0, 0, 1), new Vector3())
            });
            void onMouseEvent(string name, MouseEventRuntime mer)
            {
                if (name == "Move")
                {
                    if (!startPush)
                    {
                        if (startP == null)
                        {
                            return;
                        }

                        endP = this.snap3dRuntime.SnapPoint.Clone();
                        if (endP != null)
                        {
                            this.CreateOrUpdateCylinder(startP, endP, 1);
                        }
                    }
                    else
                    {
                        if (solidEle != null && pr != null&& this.snap3dRuntime.SnapPoint!=null)
                        {
                            Move(this.snap3dRuntime.SnapPoint);
                        }
                    }
                }
                else if (name == "Down")
                {
                    if (startP == null)
                    {
                        startP = this.snap3dRuntime.SnapPoint.Clone();
                    }
                    else if (!startPush)
                    {
                        startPush = true;
                        var topFace = this.cylinder.Solid.TopoFaceModel.Surfaces[2];
                        pr = new FaceInputerResult()
                        {
                            Surface = topFace,
                            Element = this.cylinder,
                            SnapPoint = this.snap3dRuntime.SnapPoint.Clone()
                        };

                        plane = pr.Surface as PlanarSurface3d;
                        solidEle = pr.Element as LcSolid3d;
                        this.snap3dRuntime.ClearSnapPlanes();
                        var camera = this.snap3dRuntime.GetCamera();
                        var yAxis = camera.getWorldDirection().Negate().Cross(plane.Normal).Normalize();
                        var zAxis = plane.Normal.Clone().Cross(yAxis).Normalize();
                        this.snap3dRuntime.AddSnapPlanes(new ListEx<Plane>
                        {
                            new Plane().SetFromNormalAndCoplanarPoint(zAxis,pr.SnapPoint)
                        });
                    }
                    else if (startPush)
                    {
                        this.snap3dRuntime.EndSnaping();
                        this.model3dRuntime.Control.DetachEvents(null, null, onMouseEvent, null, null, null, null);
                        this.snap3dRuntime.ClearSnapPlanes();
                        this.model3dRuntime.EnableCameraControl(true);
                    }
                }
            }

            void Move(Vector3 target)
            {
                CreateOrUpdateCylinder(startP, endP, target.Z);
            }
            this.snap3dRuntime.StartSnaping(SnapFilterType.OnlyPlane);
            this.model3dRuntime.Control.AttachEvents(null, null, onMouseEvent, null, null, null, null);
            EndAction();
        }
        public void CreateOrUpdateCylinder(Vector3 start, Vector3 end, double depth)
        {
            if (this.cylinder != null)
            {
                this.docRt.Document.ModelSpace.RemoveElement(this.cylinder);
            }
            var mats = new LcMaterial[3]
            {
                new LcMaterial() { Color = new Color(0xff0000) },
                new LcMaterial() { Color = new Color(0x00ff00) },
                new LcMaterial() { Color = new Color(0x0000ff) },
            };
            Vector3 cenOffset = (end - start).MulScalar(0.5);
            double width = Math.Abs(end.X - start.X);
            double height = Math.Abs(end.Y - start.Y);
            double distance = end.DistanceTo(start);
            this.cylinder = new LcCylinder(distance, distance, depth, 0, Utils.TwoPI, 32, false, mats);
            this.cylinder.Solid.Topoable = true;
            this.cylinder.Initilize(this.docRt.Document);
            this.cylinder.Rt3DAction = this;
            this.cylinder.Position = start.Clone();
            this.cylinder.UpdateMatrix();
            this.docRt.Document.ModelSpace.InsertElement(this.cylinder);
        }
    }

    public class Ellipsoid3dAction : Solid3dAction
    {
        public Ellipsoid3dAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令：Ellipsoid");
        }
        public async void ExecCreate(string[] args = null)
        {
            var mats = new LcMaterial[4]
            {
                new LcMaterial() { Color = new Color(0xff0000) },
                new LcMaterial() { Color = new Color(0x00ff00) },
                new LcMaterial() { Color = new Color(0x0000ff) },
                new LcMaterial() { Color = new Color(0xff00ff) }
            };
            var Ellipsoid = new LcEllipsoid(1000, 800, 500, Math.PI * 3 / 4, Math.PI / 4, mats);
            Ellipsoid.Initilize(this.docRt.Document);
            Ellipsoid.UpdateMatrix();
            Ellipsoid.Rt3DAction = this;
            this.docRt.Document.ModelSpace.InsertElement(Ellipsoid);
        }
    }
    public class Sphere3dAction : Solid3dAction
    {
        public Sphere3dAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令：Sphere");
        }
        public async void ExecCreate(string[] args = null)
        {
            var mats = new LcMaterial[4]
            {
                new LcMaterial() { Color = new Color(0xff0000) },
                new LcMaterial() { Color = new Color(0x00ff00) },
                new LcMaterial() { Color = new Color(0x0000ff) },
                new LcMaterial() { Color = new Color(0xff00ff) },
            };

            var Sphere = new LcSphere(1000, -Math.PI / 4, Math.PI, mats);
            Sphere.Initilize(this.docRt.Document);
            Sphere.UpdateMatrix();
            Sphere.Rt3DAction = this;
            this.docRt.Document.ModelSpace.InsertElement(Sphere);
        }
    }
}
